package com.changgou.seckill.task;

import com.alibaba.fastjson.JSON;
import com.changgou.entity.IdWorker;
import com.changgou.entity.SeckillStatus;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MultiThreadingCreateOrder {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //异步执行，底层多线程
    @Async
    public void createOrder() {
        try {
            System.out.println("准备睡会了再下单");
            Thread.sleep(1000);
            //从Redis队列中获取用户排队信息
            SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps("SeckillQueue").rightPop();
            if (seckillStatus == null) {
                return;
            }
            String time = seckillStatus.getTime();
            Long id = seckillStatus.getGoodsId();
            String userId = seckillStatus.getUserId();

            //先到SeckillGoodsCountList_ID队列中获取该商品的一个信息，如果能获取，则可以下单
            Object sgoods = redisTemplate.boundListOps("Secki1lGoodsCountList_" + seckillStatus.getGoodsId()).rightPop();
            //如果不能获取该商品的队列信息，则表示没有库存，清理排队信息
            if (sgoods == null) {
                //没有库存，清空排队信息
                ClearUserQueue(seckillStatus.getUserId());
                return;
            }

            String namespace = "SeckillGoods_" + time;

            SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(namespace).get(id);
            //判断有没有库存
            if (seckillGoods == null || seckillGoods.getStockCount() <= 0) {
                //100表示无库存
                throw new RuntimeException("已售密!");
            }
            //创建订单对象
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setId(idWorker.nextId());
            seckillOrder.setSeckillId(id); //商品ID
            seckillOrder.setMoney(seckillGoods.getCostPrice()); //支付金额
            seckillOrder.setUserId(userId); //用户名
            seckillOrder.setCreateTime(new Date()); //创建时间
            seckillGoods.setStatus("0");

            //将订单对象存储起来
            redisTemplate.boundHashOps("SeckillOrder").put(userId, seckillOrder);

            //库存递减
            seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getId() + "操作后剩余库存" + seckillGoods.getStockCount());
            //库存为0，就同步数据库
            //第一个方法获取队列数量
            //第二个方法 redis 里面stockcount -1，为-1<0  库存没有，同步数据库
            Long size = redisTemplate.boundListOps("Secki1lGoodsCountList_" + seckillStatus.getGoodsId()).size();

            if (size <= 0) {
                //同步数量
                seckillGoods.setStockCount(size.intValue());
                //同步数据到MySQL
                seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
                //删除Redis中的商品数据
                redisTemplate.boundHashOps(namespace).delete(id);
            } else {
                //数量更新过后，同步数据到Redis,更新商品队列
                redisTemplate.boundHashOps(namespace).put(id, seckillGoods);
            }
            //更新下单状态
            seckillStatus.setOrderId(seckillOrder.getId()); //id .
            seckillStatus.setMoney(Float.valueOf(seckillGoods.getCostPrice())); //支付金额
            seckillStatus.setStatus(2); //代付款
            //更新排队队列
            redisTemplate.boundHashOps("UserQueueStatus").put(userId, seckillStatus);

            rabbitTemplate.convertAndSend("seckillDelayQueue", (Object) JSON.toJSONString(seckillStatus), new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties().setExpiration("10000");
                    return message;
                }
            });
            System.out.println("下单完成");
            //===================支付有前端发起调用pay
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清理用户排队抢单信息
     */
    public void ClearUserQueue(String userId) {
        //删除排队自增标识
        redisTemplate.boundHashOps("UserQueueCount").delete(userId);
        //删除排队信息
        redisTemplate.boundHashOps("UserQueueStatus").delete(userId);
    }
}
